package xs.szw.service.filter;

import com.alibaba.fastjson2.JSON;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import xs.szw.common.constant.RedisKeyConstant;
import xs.szw.common.constant.SecurityConstants;
import xs.szw.common.exception.BusinessException;
import xs.szw.common.result.ResultCode;
import xs.szw.common.utils.JwtUtil;
import xs.szw.common.utils.ServletUtils;
import xs.szw.service.model.pojo.security.LoginUser;
import xs.szw.service.utils.RedisCache;

import java.io.IOException;

/**
 * @program: My_SpringSecurity
 * @description: jwt过滤器
 * @author: Songzw
 * @create: 2025-01-29 16:28
 **/
@Component
@Slf4j
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {

    private static final String BEARER_PREFIX = "Bearer ";

    private final RedisCache redisCache;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.获取Token
//        String token = request.getHeader("token");
        //2.获取token
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        log.info("token: " + token);
        //token == null || token.isBlank() java 11判断字符串是否为空
        if (!StringUtils.hasText(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        //判断token是否有前缀 JWT_TOKEN_PREFIX
        if(!token.startsWith(SecurityConstants.JWT_TOKEN_PREFIX)){
            ServletUtils.writeErrMsg(response, ResultCode.ACCESS_TOKEN_INVALID);
            return;
        }
        // 去除 Bearer 前缀
        token = token.substring(SecurityConstants.JWT_TOKEN_PREFIX.length());
        //解析Token
        Long id;
        LoginUser u;
        try {
            Claims claims = JwtUtil.parseJWT(token);
            u = JSON.parseObject(claims.getSubject(), LoginUser.class);
            id = u.getUser().getId();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("token非法");
        }
        //redis中获取信息
        String jwt = redisCache.getCacheObject(RedisKeyConstant.RBAC_Login_KEY + id);
        if (!StringUtils.hasText(jwt)) {
            throw new BusinessException(ResultCode.ACCESS_TOKEN_INVALID);
        }
        //存入SecurityContextHolder
        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(u, null, u.getAuthorities()));
        filterChain.doFilter(request, response);
    }

}
